﻿using BalanceControl.Comm.Codec;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BalanceControl.Comm
{
    public class TcpHandler
    {
        public Action<byte[]> DataReceived { get; set; }
        public Action<byte[]> FrameReceived { get; set; }

        protected Socket mSocket;//内部Socket对象
        private ICodec mCodec;

        public TcpHandler()
        {
            mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            mCodec = new FixLengthWithHeaderCodec(7);
        }

        public bool IsConnect
        {
            get
            {
                return mSocket.Connected;
            }
        }


        public bool Connect(string host, int port, Action<bool> callback = null)
        {
            try
            {
                IAsyncResult conAsync = mSocket.BeginConnect(host, port, (iar) =>
                {
                    callback?.Invoke(mSocket.Connected);
                    if (mSocket.Connected)
                    {
                        Thread thread = new Thread(TCPReceive);//启动一个线程接收请求
                        thread.IsBackground = true;
                        thread.Start();//启动线程
                    }
                }, mSocket);//开始连接
            }
            catch (Exception ex)
            {
                return false;
            }

            return true;
        }

        public bool DisConnect()
        {
            if (mSocket.Connected)
            {
                mSocket.Close();
                return true;
            }
            return false;
        }
        private void TCPReceive()
        {
            while (true)
            {
                try
                {
                    if (mSocket != null && mSocket.Connected)
                    {
                        int readLen = mSocket.Available;
                        if (readLen > 0)
                        {
                            byte[] recvBytes = new byte[readLen];
                            int rec = mSocket.Receive(recvBytes);//从网络流中读取数据
                            if (rec != 0)
                            {
                                List<Object> result = mCodec.decode(new List<Object>() { recvBytes });
                                foreach (Object obj in result)
                                {
                                    if (obj is byte[])
                                    {
                                        byte[] frame = obj as byte[];
                                        FrameReceived?.Invoke(frame);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {

                }
                Thread.Sleep(10);
            }
        }

        public void Transmit(byte[] data)
        {
            if (mSocket.Connected)
            {
                mSocket.Send(data);
            }
        }
    }
}
